<?php
namespace restphp\common\wx;

use restphp\biz\RestErrorCode;
use restphp\exception\RestException;
use restphp\utils\RestClassUtils;
use restphp\utils\RestClientCurlUtils;
use restphp\utils\RestClientUtils;
use restphp\utils\RestLog;
use restphp\utils\RestStringUtils;

/**
 * Class WeChatMiniProcessAuthApi
 * @package restphp\common\wx
 */
class WeChatMiniProcessAuthApi {
    const API_URL_HEAD = "https://api.weixin.qq.com";

    protected static $_uriAuth = self::API_URL_HEAD . "/sns/jscode2session?appid={appid}&secret={secret}&js_code={js_code}&grant_type=authorization_code";
    protected static $_uriInfo = self::API_URL_HEAD . "/sns/userinfo?access_token=%s&openid=%s";
    protected static $_uriToken = self::API_URL_HEAD . "/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}";

    protected static $_appId = '';
    protected static $_secret = '';

    protected static function formatUrl($url) {
        $strUrl = str_replace("{appid}", self::$_appId, $url);
        $strUrl = str_replace("{secret}", self::$_secret, $strUrl);
        return $strUrl;
    }

    public static function init($appId, $secret) {
        self::$_appId = $appId;
        self::$_secret = $secret;
    }

    /**
     * 获取openId.
     * @param $code
     * @return mixed
     * @throws RestException
     */
    public static function getOpenId($code) {
        $apiUrl = self::formatUrl(self::$_uriAuth);
        $apiUrl = str_replace("{js_code}", $code, $apiUrl);

        $arrInfo = RestClientCurlUtils::getV2($apiUrl);

        if (!isset($arrInfo['body'])) {
            throw new RestException('ERR_WECHAT_REQUEST_FAIL', RestErrorCode::ERR_WECHAT_REQUEST_FAIL);
        }
        $strBody = $arrInfo['body'];
        if (RestStringUtils::isBlank($strBody)) {
            throw new RestException('ERR_WECHAT_REQUEST_FAIL', RestErrorCode::ERR_WECHAT_REQUEST_FAIL);
        }

        $arrBody = json_decode($strBody, true);

        $errorCode = isset($arrBody['session_key']) ? "0" : (isset($arrBody['errcode']) ? $arrBody['errcode'] : "-99");
        if ("0" != $errorCode) {
            throw new RestException($errorCode, isset($arrBody['errmsg']) ? $arrBody['errmsg'] : 'unknown error');
        }

        return $arrBody['openid'];
    }

    /**
     * @return mixed|string
     * @throws RestException
     */
    public static function getAccessToken() {
        $apiUrl = self::formatUrl(self::$_uriToken);

        $arrInfo = RestClientCurlUtils::getV2($apiUrl);
        RestLog::writeLog("请求微信息认证地址：" . $apiUrl . "；返回结果：" . json_encode($arrInfo));

        if (!isset($arrInfo['body'])) {
            throw new RestException('ERR_WECHAT_REQUEST_FAIL', RestErrorCode::ERR_WECHAT_REQUEST_FAIL);
        }
        $strBody = $arrInfo['body'];
        if (RestStringUtils::isBlank($strBody)) {
            throw new RestException('ERR_WECHAT_REQUEST_FAIL', RestErrorCode::ERR_WECHAT_REQUEST_FAIL);
        }

        $arrBody = json_decode($strBody, true);
        return isset($arrBody['access_token']) ? $arrBody['access_token'] : '';
    }

    /**
     * @param $openId
     * @return WxUserInfo
     * @throws RestException
     */
    public static function getUserData($openId) {
        $accessToken = self::getAccessToken();
        $uriInfo = sprintf(self::$_uriInfo, $accessToken, $openId);

        $userInfoData = RestClientUtils::get($uriInfo);
        if (RestStringUtils::isBlank($userInfoData)) {
            throw new RestException('WX_LOGIN_GET_USER_INFO_ERROR', RestErrorCode::WX_LOGIN_GET_USER_INFO_ERROR);
        }

        $userInfo = RestClassUtils::parseObject($userInfoData, WxUserInfo::class);
        if (null == $userInfo || null == $userInfo->getNickname()) {
            throw new RestException('WX_LOGIN_GET_USER_INFO_ERROR', RestErrorCode::WX_LOGIN_GET_USER_INFO_ERROR);
        }
        return $userInfo;
    }
}